Messages in SkeldJS have been designed to be easy to both write and to register to a client or server using the PacketDecoder class.
The very basic structure of a message declaration is as follows:
class MyFavouriteMessage extends BaseMessage {
static tag = 1 as const; // The hazel message tag.
tag = 1 as const;
constructor() {
}
static Deserialize(
reader: HazelReader, // The message reader to read the message from.
direction: MessageDirection, // The direction that this message is travelling in.
decoder: PacketDecoder // The decoder that this message is going through.
) {
// Should return an instance of MyFavouriteMessage
}
Serialize(
writer: HazelWriter, // The message writer to write the message to.
direction: MessageDirection,
decoder: PacketDecoder
) {
}
}
A message declaration is just a class that optionally extends one of several utility classes for standardisation, here being a very basic BaseMessage which just contains a utility for cancelling the message in some scenarios (such as if it is relayed through a server, you might want to stop this behaviour).
Otherwise, SkeldJS also contains several other classes based off of the Among Us protocol to extend:
BaseRootPacket - used for writing protocol send options, see here for more information.
BaseRootMessage - used for writing root messages, see here for more information.
BaseGameDataMessage - used for writing game data messages, see here for more information.
BaseRpcMessage - used for writing remote call procedure messages, see here for more information.
Using the above classes rather than extending BaseMessage
means that you don't need to specify the message type, since they will be set to option
, root
, gamedata
and rpc
respectfully if you extend them.
The Deserialize and Serialize methods take 3 parameters, a HazelReader or HazelWriter instance respectfully, and also both take a MessageDirection and PacketDecoder.
The Deserialize method should also return an instance of the message, while Serialize should return nothing.
Of course, SkeldJS contains plenty of examples and real-world usecases of writing messages, https://github.com/SkeldJS/SkeldJS/tree/master/packages/protocol/lib/packets.
To see an example of a custom message in the wild, I have several examples on my server implementation, Hindenburg, here
To register a custom message, you can use the PacketDecoder#register method, passing in the message class declaration itself. (Not an instance of the message)
To listen for a message to pass through the decoder, you can use the PacketDecoder#on method, passing in the message class declaration itself and a function with 3 optional parameters,
For example, you can do
const packetDecoder = new PacketDecoder;
packetDecoder.register(MyFavouriteMessage);
packetDecoder.on(MyFavouriteMessage, (message, direction, sender) => {
console.log("Got my favourite message from %s", sender.username);
});
to register and listen for your favourite message ever.
Generated using TypeDoc